#ifndef FASTNET_NETWORK_HH
#define FASTNET_NETWORK_HH

#include <set>
#include <utility>
#include <memory>

#include "node.hh"
#include "connection.hh"
#include "tree.hh"

namespace cppn {
    class CPPN;
}

namespace brain {

    class Builder {
        cppn::CPPN* cppn;
        std::unique_ptr<Tree> tree;    
        std::set<Node> inputs;
        std::set<Node> outputs;
        std::set<Node> hidden;
        std::set<Connection> connections;

    public:

        Builder (cppn::CPPN* cppn) : cppn(cppn), tree(make_unique<Tree>(cppn))
        {
        }

        void add_input (float x, float y) {
            inputs.insert({x, y});
        }

        void add_output (float x, float y) {
            outputs.insert({x, y});
        }

        template <template <class, class> class List, class U>
        void add_inputs (List<std::pair<float, float>, U> const& inputs) {
            for (auto const& pair: inputs) add_input(pair.first, pair.second);
        }

        template <template <class, class> class List, class U>
        void add_outputs (List<std::pair<float, float>, U> const& outputs) {
            for (auto const& pair: outputs) add_output(pair.first, pair.second);
        }


        void construct();


    public:
        void print();
        void print(Node const& node);

        std::set<Node> const& get_hidden_nodes() const { return hidden; }
        std::set<Node> const& get_input_nodes() const { return inputs; }
        std::set<Node> const& get_output_nodes() const { return outputs; }
        std::set<Connection> const& get_connections() const { return connections; }
        cppn::CPPN* get_cppn () const { return cppn; }
    };
}

#endif
